import { InfluxDB, Point, WriteApi, QueryApi } from '@influxdata/influxdb-client';
import { config } from '../config';
import { DataPoint } from '../types';

export class InfluxService {
  private client: InfluxDB | null = null;
  private writeApi: WriteApi | null = null;
  private queryApi: QueryApi | null = null;

  async initialize(): Promise<void> {
    try {
      // 创建InfluxDB客户端
      this.client = new InfluxDB({
        url: config.influx.url,
        token: config.influx.token,
      });

      // 创建写入API
      this.writeApi = this.client.getWriteApi(config.influx.org, config.influx.bucket);
      
      // 配置写入选项
      this.writeApi.useDefaultTags({
        app: 'iot-data-processor',
        version: '1.0.0',
      });

      // 创建查询API
      this.queryApi = this.client.getQueryApi(config.influx.org);

      console.log('✅ InfluxDB 客户端初始化成功');
      
      // 测试连接
      await this.testConnection();
      
    } catch (error) {
      console.error('❌ InfluxDB 初始化失败:', error);
      throw error;
    }
  }

  private async testConnection(): Promise<void> {
    try {
      if (!this.queryApi) {
        throw new Error('查询API未初始化');
      }

      // 执行简单的查询来测试连接
      const query = `from(bucket: "${config.influx.bucket}") |> range(start: -1m) |> limit(n: 1)`;
      
      await new Promise((resolve, reject) => {
        let hasData = false;
        
        this.queryApi!.queryRows(query, {
          next: () => {
            hasData = true;
          },
          error: (error) => {
            // 如果是因为没有数据而出错，这是正常的
            if (error.message.includes('no data')) {
              resolve(void 0);
            } else {
              reject(error);
            }
          },
          complete: () => {
            resolve(void 0);
          },
        });
      });

      console.log('✅ InfluxDB 连接测试成功');
    } catch (error) {
      console.warn('⚠️ InfluxDB 连接测试失败，但服务仍可继续运行:', error);
    }
  }

  async writePoints(dataPoints: DataPoint[]): Promise<void> {
    if (!this.writeApi) {
      throw new Error('InfluxDB 写入API未初始化');
    }

    try {
      const points = dataPoints.map(dp => this.createPoint(dp));
      
      // 写入数据点
      this.writeApi.writePoints(points);
      
      // 刷新缓冲区（可选，会立即写入）
      await this.writeApi.flush();
      
      console.log(`✅ 已写入 ${dataPoints.length} 个数据点到 InfluxDB`);
      
    } catch (error) {
      console.error('❌ 写入 InfluxDB 失败:', error);
      throw error;
    }
  }

  private createPoint(dataPoint: DataPoint): Point {
    const point = new Point(dataPoint.measurement);

    // 添加标签
    Object.entries(dataPoint.tags).forEach(([key, value]) => {
      point.tag(key, value);
    });

    // 添加字段
    Object.entries(dataPoint.fields).forEach(([key, value]) => {
      if (typeof value === 'number') {
        point.floatField(key, value);
      } else if (typeof value === 'string') {
        point.stringField(key, value);
      } else if (typeof value === 'boolean') {
        point.booleanField(key, value);
      }
    });

    // 设置时间戳
    if (dataPoint.timestamp) {
      point.timestamp(dataPoint.timestamp);
    }

    return point;
  }

  // 查询数据方法
  async queryData(query: string): Promise<any[]> {
    if (!this.queryApi) {
      throw new Error('InfluxDB 查询API未初始化');
    }

    const results: any[] = [];

    return new Promise((resolve, reject) => {
      this.queryApi!.queryRows(query, {
        next: (row, tableMeta) => {
          const record = tableMeta.toObject(row);
          results.push(record);
        },
        error: (error) => {
          reject(error);
        },
        complete: () => {
          resolve(results);
        },
      });
    });
  }

  // 获取设备最新数据
  async getLatestDeviceData(deviceId: string, limit: number = 10): Promise<any[]> {
    const query = `
      from(bucket: "${config.influx.bucket}")
        |> range(start: -24h)
        |> filter(fn: (r) => r.deviceId == "${deviceId}")
        |> sort(columns: ["_time"], desc: true)
        |> limit(n: ${limit})
    `;

    return this.queryData(query);
  }

  // 获取设备统计信息
  async getDeviceStats(deviceId: string, timeRange: string = '-1h'): Promise<any[]> {
    const query = `
      from(bucket: "${config.influx.bucket}")
        |> range(start: ${timeRange})
        |> filter(fn: (r) => r.deviceId == "${deviceId}")
        |> group(columns: ["metric"])
        |> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
    `;

    return this.queryData(query);
  }

  async close(): Promise<void> {
    try {
      if (this.writeApi) {
        await this.writeApi.close();
        console.log('✅ InfluxDB 写入API已关闭');
      }
      
      if (this.client) {
        // InfluxDB客户端没有显式的关闭方法，但可以清理引用
        this.client = null;
        this.writeApi = null;
        this.queryApi = null;
        console.log('✅ InfluxDB 客户端已清理');
      }
    } catch (error) {
      console.error('❌ 关闭 InfluxDB 连接时出错:', error);
    }
  }
}
